package com.pay.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pay.constant.Constant;
import com.pay.entity.Merchant;
import com.pay.entity.Order;
import com.pay.entity.ZfbInLog;
import com.pay.entity.ZfbMember;
import com.pay.enums.MerchantAccountTypeEnums;
import com.pay.exception.ServiceException;
import com.pay.mapper.ZfbInLogMapper;
import com.pay.notify.ZfbNotifyHandler;
import com.pay.service.IMerchantAccountService;
import com.pay.service.IMerchantService;
import com.pay.service.IOrderService;
import com.pay.service.IZfbInLogService;
import com.pay.service.IZfbMemberService;
import com.pay.utils.BasePage;
import com.pay.utils.FunctionUtils;

import cn.hutool.core.util.StrUtil;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Peng
 * @since 2018-12-05
 */
@Service
public class ZfbInLogServiceImpl extends ServiceImpl<ZfbInLogMapper, ZfbInLog> implements IZfbInLogService {

	@Autowired
	private IZfbMemberService zfbMemberService ;
	
	@Autowired
	private IMerchantService merchantService ;
	
	@Autowired
	private IOrderService orderService ;
	
	@Autowired
	private IMerchantAccountService merchantAccountService ;
	
	private Lock lock = new ReentrantLock() ;
	
	@Override
	public void handlePay(Integer robtoId, String tradeNo, BigDecimal account, String goodsTitle,String otherAccountFullname) {
		try {
			lock.lock();
			ZfbMember zfbMember = zfbMemberService.getById(robtoId);
			if(zfbMember == null) {
				return ;
			}
			boolean exists = FunctionUtils.isBloomFilter(tradeNo);
			ZfbInLog zfbInLog = getByTradeNo(tradeNo);
			if(!exists) {
				//不存在
				if(zfbInLog == null) {
					BigDecimal original = zfbMember.getTotalmoney();
					BigDecimal last = FunctionUtils.add(original, account, 2) ;
					zfbMember.setTotalmoney(last); ;
					zfbMemberService.updateById(zfbMember) ;
					
					/**
					 * 添加机器人收款记录
					 */
					zfbInLog = new ZfbInLog();
					zfbInLog.setMemberId(zfbMember.getId());
					zfbInLog.setMoney(account); 
					zfbInLog.setTradeNo(tradeNo); 
					zfbInLog.setFlagcode(goodsTitle);
					zfbInLog.setTransname(otherAccountFullname);
					boolean result = super.save(zfbInLog);
					if(!result) {
						throw new ServiceException("保存机器人收款金额异常") ;
					}
				}
			}
			
			/**
			 * 查询下有没有符合要求的订单
			 */
			BigDecimal accountMi = FunctionUtils.mul(zfbInLog.getMoney(), new BigDecimal(100), 2) ;
			Order order = orderService.getOne(new QueryWrapper<Order>()
					.eq("flagcode", zfbInLog.getFlagcode())
					.eq("amount", accountMi)
					.eq("paystatus", Constant.pay_wait)
					.orderByDesc("id"));
			
			if(order != null) {
				//说明有支付回调
				
				Merchant merchant = merchantService.getById(order.getMerchantId());
				
				if(merchant.getModel() == Constant.merchant_to_public) {
					//对公
					
					String detailResult = merchantAccountService.insertAccountDetail(merchant.getId(), MerchantAccountTypeEnums.orderIn.getId(), Constant.pay_in, 
							FunctionUtils.div(new BigDecimal(order.getMerchantAmount()), new BigDecimal(100), 2), "支付收款到账");
					
					if(StrUtil.isNotBlank(detailResult)) {
						throw new ServiceException("添加商户金额明细失败") ;
					}
				}else {
					//对私
					String detailResult = merchantAccountService.insertAccountDetail(merchant.getId(), 
							MerchantAccountTypeEnums.tax_out.getId(), Constant.pay_out,FunctionUtils.div(new BigDecimal(order.getTaxAmount()), new BigDecimal(100), 2)
							, "费率扣除");
					
					if(StrUtil.isNotBlank(detailResult)) {
						throw new ServiceException("商户金额明细修改失败") ;
					}
				}
				
				
				/**
				 * 完成订单
				 */
				order.setSuccesstime(new Date());
				order.setPaystatus(Constant.pay_success);
				orderService.updateById(order) ; //更新订单
				
				
				
				/**
				 * 回调操作
				 */
				ZfbNotifyHandler notifyHandler = new ZfbNotifyHandler();
				notifyHandler.setOrder(order);
				new Thread(notifyHandler).start(); 
			}
			
			FunctionUtils.addBloomFilter(tradeNo);
		}catch(Exception e) {
			e.printStackTrace();
			throw e ;
		}finally {
			lock.unlock();
		}
		
	}

	@Override
	public ZfbInLog getByTradeNo(String tradeNo) {
		return super.getOne(new QueryWrapper<ZfbInLog>().eq("trade_no", tradeNo)) ;
	}

	
	@Override
	public void getList(ZfbInLog zfbInLog, BasePage<ZfbInLog> page) {
		page.setSize(20) ; //每页20条
		QueryWrapper<ZfbInLog> ew = new QueryWrapper<ZfbInLog>();
		ew.orderByDesc("id") ;
		if(zfbInLog.getMemberId() != null) {
			ew.eq("member_id", zfbInLog.getMemberId()) ;
		}
		
		if(page.isPage()) {
			super.page(page, ew) ;
		}else {
			List<ZfbInLog> data = super.list(ew);
			int total = super.count(ew);
			page.setRecords(data) ;
			page.setTotal(total) ;
		}
		
		for(ZfbInLog log : page.getRecords()) {
			ZfbMember zfbMember = zfbMemberService.getById(log.getMemberId());
			log.setZfbMember(zfbMember);
		}
	}

}
